//
//  YZSHTTPRequestOperationManager.m
//  YZStock
//
//  Created by fenchol on 15/9/1.
//  Copyright (c) 2015年 cqjr. All rights reserved.
//

#import "YZHTTPRequestOperationManager.h"
#import "YZRequestURLs.h"
#import "NSError+YZM.h"
#import "YZMantleSerialization.h"
#import "YZMUserService.h"
#import "YZGeneralResultModel.h"
#import "YZRequestURLs.h"
#import <DateTools/DateTools.h>

static NSTimeInterval slastAutoInterval = 0;

@implementation YZHTTPRequestOperationManager

- (NSMutableDictionary *)addDelegateParam:(NSDictionary *)params {
    
    NSMutableDictionary *mutableParams= [NSMutableDictionary dictionaryWithDictionary:params];
    //区分代理商
#ifdef YZMicroStock
    mutableParams[@"agentCode"] = @"YZTZ";
#elif YZMicroStock_Agent_One
    mutableParams[@"agentCode"] = @"One";
#elif YZMicroStock_Agent_GPZQSQ
    mutableParams[@"agentCode"] = @"GPZQSQ";
#endif
    return mutableParams;
}

- (NSURLSessionDataTask *)cqHTTPRequestOperationWithHTTPMethod:(NSString *)method
                                                       URLString:(NSString *)URLString
                                                     cachePolicy:(NSURLRequestCachePolicy)cachePolicy
                                                      parameters:(id)parameters
                                                         success:(void (^)(NSURLSessionDataTask *operation, id responseObject))success
                                                         failure:(void (^)(NSURLSessionDataTask *operation, NSError *error))failure
{
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:[self addDelegateParam:parameters] error:&serializationError];
    if (serializationError) {
        if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
#pragma clang diagnostic pop
        }
        
        return nil;
    }
    
    request.cachePolicy = cachePolicy;
    
    return [self HTTPRequestOperationWithRequest:request success:success failure:failure];
}

- (NSURLSessionDataTask *)cq_noCachePOST:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
{
    NSURLSessionDataTask *operation = [self cqHTTPRequestOperationWithHTTPMethod: @"POST"
                                                                         URLString: URLString
                                                                       cachePolicy: NSURLRequestReloadIgnoringCacheData
                                                                        parameters: parameters
                                                                           success: success
                                                                           failure: failure];
    
    [operation resume];
    
    return operation;
}

- (NSURLSessionDataTask *)cq_noCacheGET:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask * task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
{
    NSURLSessionDataTask *operation = [self cqHTTPRequestOperationWithHTTPMethod: @"GET"
                                                                         URLString: URLString
                                                                       cachePolicy: NSURLRequestReloadIgnoringCacheData
                                                                        parameters: parameters
                                                                           success: success
                                                                           failure: failure];
    [operation resume];
    return operation;
}

- (NSURLSessionDownloadTask *)cq_noCacheDownload:(NSString *)URLString filepath:(NSString*)filepath parameters:(id)parameters success:(void (^)(NSURLSessionDownloadTask *, id))success failure:(void (^)(NSURLSessionDownloadTask *, NSError *))failure
{
    //构建请求
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
    if (serializationError) {
        if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
#pragma clang diagnostic pop
        }
        
        return nil;
    }
    //读取文件最后修改时间（服务器文件修改时间）
    NSString *lastModifiedStr = [NSString stringWithContentsOfFile:[filepath stringByAppendingString:@".date"] encoding:NSUTF8StringEncoding error:nil];
    if (lastModifiedStr.length > 0) {
        lastModifiedStr = [lastModifiedStr componentsSeparatedByString:@"||"][0];
    }
    if ([[NSFileManager defaultManager] fileExistsAtPath:filepath]) {
        [request addValue:lastModifiedStr forHTTPHeaderField:@"If-Modified-Since"];//添加modified 参数
    }
    //下载文件
    __block NSURLSessionDownloadTask *dataTask = nil;
    __block NSString *downloadPath = filepath;
    //删除本地旧文件
    dataTask = [self downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        NSLog(@"downloaded:%lld", downloadProgress.completedUnitCount);
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {//返回下载路径
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        if ([httpResponse statusCode] == 200) {//状态正确返回下载路径
            [[NSFileManager defaultManager] removeItemAtPath:downloadPath error:nil];
            return [NSURL fileURLWithPath:downloadPath];
        } else {
            return nil;
        }
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {//下载完成
        if ([error code] == -1202) {//证书错误，设置成信任证书模式
            self.securityPolicy.allowInvalidCertificates = YES;
            self.securityPolicy.validatesDomainName = NO;
            self.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        }
        if (error) {//下载失败
            if (failure) {
                failure(dataTask, error);
            }
        } else {//下载成功
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            if ([httpResponse statusCode] == 200 && success) {
                //写入文件修改时间
                NSString *modified = [httpResponse allHeaderFields][@"Last-Modified"];
                NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
                [dateFormatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss zzz"];
                NSDate *modifyDate = [dateFormatter dateFromString:modified];
                double doubleDate = [modifyDate timeIntervalSince1970];
                if (doubleDate < 1) {//没有读到修改时间的话用当前最新时间替代
                    doubleDate = [[NSDate date] timeIntervalSince1970];
                }
                modified = [modified stringByAppendingFormat:@"||%f", doubleDate];
                NSString *absoluteString = [[filePath absoluteString] stringByReplacingOccurrencesOfString:@"file://" withString:@""];
                NSLog(@"modified date is: %@", modified);
                [modified writeToFile:[absoluteString stringByAppendingString:@".date"] atomically:YES encoding:NSUTF8StringEncoding error:nil];
                success(dataTask, absoluteString);
            }
        }
    }];
    [dataTask resume];
    return dataTask;
}


- (NSURLSessionDataTask *)cq_noCachePOSTData:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block success:(void (^)(NSURLSessionDataTask *, id))success failure:(void (^)(NSURLSessionDataTask *, NSError *))failure{
    
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:nil];
    if (serializationError) {
        if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
#pragma clang diagnostic pop
        }
        
        return nil;
    }
    
    request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
    NSURLSessionDataTask *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    
    [operation resume];
    return operation;
}

- (NSURLSessionDataTask *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
                                                    success:(void (^)(NSURLSessionDataTask *operation, id responseObject))success
                                                    failure:(void (^)(NSURLSessionDataTask *operation, NSError *error))failure
{
    
    __block NSURLSessionDataTask *dataTask = nil;
    
    dataTask = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
        if ([error code] == -1202) {//证书错误，设置成信任证书模式
            self.securityPolicy.allowInvalidCertificates = YES;
            self.securityPolicy.validatesDomainName = NO;
            self.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        }
        if (error) {
            if (failure) {
                failure(dataTask, error);
            }
        } else {
            
            if (responseObject == NULL) {
                NSError *error = [NSError yz_errorWithBadResponse];
                if (failure) {
                    
                    failure(dataTask, error);
                }
            }
            
            if ([responseObject isKindOfClass:[YZGeneralResultModel class]] && [responseObject checkNeedLogin]) {
                if ([request.URL.absoluteString rangeOfString: URL_FOR_LOGIN].location == NSNotFound) {
                    
                    NSTimeInterval last = [NSDate timeIntervalSinceReferenceDate];
                    if (last - slastAutoInterval > 30) {
                        [[YZMUserService sharedService] loginSuccess:^(YZMLoginResultModel *result) {
                            [self HTTPRequestOperationWithRequest: request success:success failure: failure];
                        } failure:^(NSError *error) {
                            if (failure) {
                                failure(dataTask, error);
                            }
                        }];
                        slastAutoInterval = last;
                        return;
                    }
                }
            }
            if (success) {
                success(dataTask, responseObject);
            }
        }
    }];
    
    return dataTask;
}

@end
